{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Copy makes it easy to make duplicates of existing objects. Provides functions for making shallow and deep copies of an object."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Shallow copy - A new container populated with references to the contents of the original object\n",
    "### Deep copy - A new container populated with copies of the contents of the original object"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] "
     ]
    }
   ],
   "source": [
    "import copy\n",
    "\n",
    "\n",
    "original_list = [int(x) for x in range(10)]\n",
    "print(original_list, end = ' ')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Shallow copy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] "
     ]
    }
   ],
   "source": [
    "# the reference in shallow_list is to the same object in original_list\n",
    "\n",
    "shallow_list = copy.copy(original_list)\n",
    "print(shallow_list, end = ' ')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "original_list: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n",
      "shallow_list: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n",
      "shallow_list is original_list: False\n",
      "shallow_list == original_list: True\n",
      "shallow_list[0] is original_list[0]: True\n",
      "shallow_list[0] == original_list[0]: True\n"
     ]
    }
   ],
   "source": [
    "print('original_list:', original_list)\n",
    "print('shallow_list:', shallow_list)\n",
    "print('shallow_list is original_list:', (shallow_list is original_list))\n",
    "print('shallow_list == original_list:', (shallow_list == original_list))\n",
    "print('shallow_list[0] is original_list[0]:', (shallow_list[0] is original_list[0]))\n",
    "print('shallow_list[0] == original_list[0]:', (shallow_list[0] == original_list[0]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Deepcopy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] "
     ]
    }
   ],
   "source": [
    "deep_list = copy.deepcopy(original_list)\n",
    "print(deep_list, end = ' ')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "original_list: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n",
      "deep_list: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n",
      "deep_list is original_list: False\n",
      "deep_list == original_list: True\n",
      "deep_list[0] is original_list[0]: True\n",
      "deep_list[0] == original_list[0]: True\n"
     ]
    }
   ],
   "source": [
    "print('original_list:', original_list)\n",
    "print('deep_list:', deep_list)\n",
    "print('deep_list is original_list:', (deep_list is original_list))\n",
    "print('deep_list == original_list:', (deep_list == original_list))\n",
    "print('deep_list[0] is original_list[0]:', (deep_list[0] is original_list[0])) # A class instance gives this false!\n",
    "print('deep_list[0] == original_list[0]:', (deep_list[0] == original_list[0]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Let's try this with classes!!!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "import functools\n",
    "\n",
    "@functools.total_ordering\n",
    "class someClass:\n",
    "    \n",
    "    def __init__(self, name):\n",
    "        self.name = name\n",
    "    \n",
    "    def __eq__(self, other):\n",
    "        return self.name == other.name\n",
    "\n",
    "    def __gt__(self, other):\n",
    "        return self.name > other.name"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Creating shallow copy\n",
    "\n",
    "ins = someClass('first')\n",
    "class_list =[ins]\n",
    "sh_copy = copy.copy(class_list)\n",
    "dp_copy = copy.deepcopy(class_list)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### shallow copy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "class_list: [<__main__.someClass object at 0x000001351AEA80F0>]\n",
      "sh_copy: [<__main__.someClass object at 0x000001351AEA80F0>]\n",
      "sh_copy is class_list: False\n",
      "sh_copy == class_list: True\n",
      "sh_copy[0] is class_list[0]: True\n",
      "sh_copy[0] == class_list[0]: True\n"
     ]
    }
   ],
   "source": [
    "print('class_list:', class_list)\n",
    "print('sh_copy:', sh_copy)\n",
    "print('sh_copy is class_list:', (sh_copy is class_list))\n",
    "print('sh_copy == class_list:', (sh_copy == class_list))\n",
    "print('sh_copy[0] is class_list[0]:', (sh_copy[0] is class_list[0]))\n",
    "print('sh_copy[0] == class_list[0]:', (sh_copy[0] == class_list[0]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "class_list: [<__main__.someClass object at 0x000001351AEA80F0>]\n",
      "dp_copy: [<__main__.someClass object at 0x000001351AEA8198>]\n",
      "dp_copy is class_list: False\n",
      "dp_copy == class_list: True\n",
      "dp_copy[0] is class_list[0]: False\n",
      "dp_copy[0] == class_list[0]: True\n"
     ]
    }
   ],
   "source": [
    "print('class_list:', class_list)\n",
    "print('dp_copy:', dp_copy)\n",
    "print('dp_copy is class_list:', (dp_copy is class_list))\n",
    "print('dp_copy == class_list:', (dp_copy == class_list))\n",
    "print('dp_copy[0] is class_list[0]:', (dp_copy[0] is class_list[0])) \n",
    "print('dp_copy[0] == class_list[0]:', (dp_copy[0] == class_list[0]))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
